package de.openlaboratory.labhub.core.server;

import java.io.File;
import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.Tomcat;

import de.openlaboratory.labhub.core.framework.Helper;
import de.openlaboratory.labhub.core.framework.RegistryContextListener;
import de.openlaboratory.labhub.core.framework.RuntimeFactory;
import de.openlaboratory.labhub.core.server.servlet.DefaultFrontController;

public class EmbeddedTomcatManager
{
	private static String EMBEDDED_SERVERPATH = "D:/DEV/labhub//tomcat";
	private static String WEBAPP_DIRECTORY = "webapp";
	private static int I_TOMCAT_PORT = 9090;
	private static Tomcat tomcat;

	public static void startup()
			throws LifecycleException
	{
		// initialize
		tomcat = new Tomcat();
		
		setup(tomcat);
		addListeners(tomcat);
		addApplications(tomcat);
		run(tomcat);

		System.out.println("Tomcat finished");
	}
	
	private static void addApplications(Tomcat server)
			throws LifecycleException
	{
		// add WAR file
		File jackrabbitPath = new File(getServerDirectory(), "jackrabbit-webapp-2.2.8");
		File testPath = new File(getServerDirectory());
		File examplesPath = new File(buildWebAppDirectory(), "examples"); //getWebAppDirectory() + File.separator + "examples"
		try
		{
			/*** ROOT ***/
			Context rootCtx = server.addContext("", getServerDirectory());
			RegistryContextListener registry = new RegistryContextListener();

				// --- FRONT CONTROLLER ---
				Tomcat.addServlet(rootCtx, "frontController", new DefaultFrontController());
				rootCtx.addServletMapping("/*", "frontController");
				
				// --- WELCOME FILE ---
				rootCtx.addWelcomeFile("index.html");
				
				// --- KILLER SWITCH ---
				// Tomcat.addServlet(rootCtx, "KillerSwitch", new KillerSwitch());
				// rootCtx.addServletMapping("/shutdown", "KillerSwitch");
			
				// --- SETTINGS MANAGER ---
				// Wrapper sm = Tomcat.addServlet(rootCtx, "settingsManager", new DefaultSettingsManager());
				// sm.setLoadOnStartup(1);
				// sm.load();
				
			/*** JACKRABBIT ***/
			//server.addWebapp("/jackrabbit", jackrabbitPath.getAbsolutePath());
			
			/*** TEST ***/
			server.addWebapp("/test", testPath.getAbsolutePath());
			
			/*** EXAMPLES ***/
			// -- HELLO WORLD ---
//			Context explCtx = server.addWebapp("/examples", examplesPath.getAbsolutePath());
//			Tomcat.addServlet(explCtx, "helloWorldServlet", "ch.ralscha.tomcatembed.HelloWorldServlet");
//			explCtx.addServletMapping("/helloworld", "helloWorldServlet");
			
		}
		catch (ServletException e)
		{
			e.printStackTrace();
		}
	}

	private static void addListeners(Tomcat server)
	{
		// The APR Lifecycle Listener checks for the presence of the
        // APR/native library and loads the library if it is present.
	
		StandardServer standardServer = (StandardServer) server.getServer();
		
		AprLifecycleListener listener = new AprLifecycleListener();
		standardServer.addLifecycleListener(listener);
	}

	private static void setup(Tomcat server)
	{
		server.setPort(getPort());
		server.setBaseDir(getServerDirectory());
		
        StandardHost stdHost = (StandardHost) server.getHost();
        stdHost.setContextClass("de.openlaboratory.labhub.core.server.LabHubServerContext");
        stdHost.setAppBase(buildWebAppDirectory());
        stdHost.setUnpackWARs(true);
        stdHost.setAutoDeploy(true);
        stdHost.setDeployOnStartup(true);
        
        RuntimeFactory.getLogger().info("Context: " + stdHost.getContextClass());
	}

	private static String getServerDirectory()
	{
		String embeddedServerDir = ".";
		
		try
		{
			embeddedServerDir = new File(EMBEDDED_SERVERPATH).getCanonicalPath();
			// System.setProperty("catalina.home", embeddedServerDir);
		}
		catch (IOException e2)
		{
			e2.printStackTrace();
		}
		
		return embeddedServerDir;
	}
	
	private static String buildWebAppDirectory()
	{
		String webAppDir = getServerDirectory() + File.separator + WEBAPP_DIRECTORY;
		
		return webAppDir;
	}
	
	private static int getPort()
	{
		return I_TOMCAT_PORT;
	}
	
	private static void printTomcatStatusInfo()
	{
		if (tomcat != null)
		{
			RuntimeFactory.getLogger().info("Engine name: " + tomcat.getEngine().getName());
			RuntimeFactory.getLogger().info("Default host: " + tomcat.getEngine().getDefaultHost());
			RuntimeFactory.getLogger().info("Info: " + tomcat.getEngine().getInfo());
			RuntimeFactory.getLogger().info("Realm: " + tomcat.getEngine().getRealm().getInfo());
			RuntimeFactory.getLogger().info("App base dir: " + tomcat.getHost().getAppBase());
			RuntimeFactory.getLogger().info("Host info: " + tomcat.getHost().getInfo());
			RuntimeFactory.getLogger().info("Host name: " + tomcat.getHost().getName());
		}
	}
	
	private static void run(Tomcat server)
	{
		if (Helper.isPortAvailable(getPort()))
		{
			try
			{
				server.start();
				server.getServer().await();
			}
			catch (LifecycleException e)
			{
				e.printStackTrace();
			}
			
			printTomcatStatusInfo();
		}
		else
		{
			RuntimeFactory.getLogger().warning(String.format("Port %s already in use", getPort()));
		}
	}
}
